package club.monkeywood.util.wechat;

import club.monkeywood.config.wechat.WechatConfig;
import club.monkeywood.converter.WxMappingJackson2HttpMessageConverter;
import club.monkeywood.dto.wechat.Result;
import club.monkeywood.dto.wechat.token.AccessTokenByCode;
import club.monkeywood.dto.wechat.user.UserInfo;
import club.monkeywood.enums.wechat.wxMediaEnum;
import club.monkeywood.dto.wechat.media.ImageMedia;
import club.monkeywood.dto.wechat.media.ThumbMedia;
import club.monkeywood.dto.wechat.menu.Menu;
import club.monkeywood.dto.wechat.token.AccessToken;
import club.monkeywood.dto.wechat.media.BaseMedia;
import club.monkeywood.util.file.FileUtil;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.util.IOUtils;
import com.fasterxml.jackson.databind.ObjectMapper;
import lombok.Data;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.core.io.FileSystemResource;
import org.springframework.http.*;
import org.springframework.stereotype.Component;
import org.springframework.util.ClassUtils;
import org.springframework.util.LinkedMultiValueMap;
import org.springframework.util.MultiValueMap;
import org.springframework.web.client.RestTemplate;

import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.io.UnsupportedEncodingException;
import java.net.URLEncoder;

@Component
@Data
@Slf4j
public class WechatUtil {

    @Autowired
    private WechatConfig wechatConfig;


    //public static void Init(WechatConfig ac) {
    //    wechatConfig = ac;
    //}

    private final String SNSAPI_BASE = "snsapi_base";
    private final String SNSAPI_USERINFO = "snsapi_userinfo";
    private final String SNSAPI_PRIVATEINFO = "snsapi_privateinfo";

//    获取token
    public AccessToken getAccessToken() {

        String url = wechatConfig.getACCESS_TOKEN_URL()
                .replace("APPID", wechatConfig.getAPPID())
                .replace("APPSECRET", wechatConfig.getAPPSECRET());
        RestTemplate restTemplate = new RestTemplate();
        AccessToken token = restTemplate.getForObject(url, AccessToken.class);
        log.info("AccessToken={}", token);

        return token;
    }

//    上传素材
    public String upload(String filePath, String accessToken, wxMediaEnum type) throws IOException {
        File file = new File(filePath);
        if (!file.exists() || !file.isFile()) {
            throw new IOException("文件不存在");
        }

        //设置消息请求头
        HttpHeaders headers = new HttpHeaders();
        MediaType mediaType = MediaType.parseMediaType("multipart/form-data;charset=UTF-8");//multipart/form-data  text/plain
        headers.setContentType(mediaType);
        FileSystemResource resource = new FileSystemResource(file);

        //将文件作为参数添加
        MultiValueMap<String, Object> map = new LinkedMultiValueMap<String, Object>();
        map.add("resource", resource);
        HttpEntity<MultiValueMap<String, Object>> httpEntity = new HttpEntity<MultiValueMap<String, Object>>(map, headers);

        String url = wechatConfig.getUPLOAD_URL()
                .replace("ACCESS_TOKEN", accessToken)
                .replace("TYPE",type.getType());

        RestTemplate restTemplate = new RestTemplate();
        // 进行网络请求,访问url接口
        ResponseEntity<String> responseEntity = restTemplate.exchange(url, HttpMethod.POST, httpEntity, String.class);
        // 解析返回值（返回json）
        if (responseEntity!=null&&responseEntity.getStatusCode()==HttpStatus.OK) {
            String sessionData = responseEntity.getBody();
            BaseMedia media = null;
            switch (type) {
                case MEDIA_IMAGE:
                    media = new ImageMedia();
                    media = JSON.parseObject(sessionData, ImageMedia.class);
                    log.info("media = {}", media);
                    return ((ImageMedia) media).getMedia_id();
                case MEDIA_THUMB:
                    media = new ThumbMedia();
                    media = JSON.parseObject(sessionData, ThumbMedia.class);
                    log.info("media = {}", media);
                    return ((ThumbMedia)media).getThumb_media_id();
                default:
                    return null;
            }

        } else {
            return null;
        }

    }

    //    创建菜单
    public int createMenu(String token){
        String url = wechatConfig.getCREATE_MENU_URL()
                .replace("ACCESS_TOKEN",token);

        //        读取自定义菜单配置文件
        ObjectMapper mapper = new ObjectMapper();
        Menu menu = null;
        try {
            //String path = ClassUtils.getDefaultClassLoader().getResource("").getPath()+wechatConfig.getCUSTOM_MENU_PATH();
            //解决读取jar包中资源文件问题
            InputStream stream = ClassUtils.getDefaultClassLoader().getResourceAsStream(wechatConfig.getCUSTOM_MENU_PATH());
            String menuStr = FileUtil.inputStream2String(stream);
            menu = mapper.readValue(menuStr, Menu.class);
        } catch (IOException e) {
            e.printStackTrace();
        }

        RestTemplate restTemplate = new RestTemplate();
        ResponseEntity<Result> resultResponseEntity = restTemplate.postForEntity(url, menu, Result.class);
        Result result = resultResponseEntity.getBody();
        log.info("Result={}", result);
        if(result ==null){
            return -1;
        }else{
            return result.getErrcode();
        }

    }

    //查询菜单
    public String queryMenu(String token){
        String url = wechatConfig.getQUERY_MENU_URL()
                .replace("ACCESS_TOKEN",token);
        RestTemplate restTemplate = new RestTemplate();
        ResponseEntity<String> responseEntity= restTemplate.getForEntity(url, String.class);
        String ret = responseEntity.getBody();
        log.info("菜单查询={}", ret);

        return ret;
    }

    //删除菜单
    public int deleteMenu(String token){
        String url = wechatConfig.getDELETE_MENU_URL()
                .replace("ACCESS_TOKEN",token);
        RestTemplate restTemplate = new RestTemplate();
        ResponseEntity<Result> responseEntity= restTemplate.getForEntity(url, Result.class);
        Result ret = responseEntity.getBody();
        log.info("删除菜单={}", ret);

        return ret.getErrcode();
    }

    // 拼装微信官服用户同意，获取code授权页面url
    // getUserInfoUrl:授权后重定向的回调链接地址
    // 此处为自己搭建的获取code的服务地址
    // 授权成功后微信自动跳转到获取code的服务地址
    // scope：应用授权作用域，
    // snsapi_base （不弹出授权页面，直接跳转，只能获取用户openid），
    // snsapi_userinfo （弹出授权页面，可通过openid拿到昵称、性别、所在地。并且， 即使在未关注的情况下，只要用户授权，也能获取其信息 ）
    public String buildAuthorizationUrl(String scope, String redirectUrl, String returnUrl) throws UnsupportedEncodingException {
        return wechatConfig.getAUTHORIZE_CODE_URL()
                                    .replace("APPID",wechatConfig.getAPPID())
                                    .replace("REDIRECT_URI",URLEncoder.encode(redirectUrl,"utf-8"))
                                    .replace("SCOPE",scope)
                                    .replace("STATE",URLEncoder.encode(returnUrl,"utf-8"));
    }

    //通过code换取openid
    public AccessTokenByCode getAccessTokenByCode(String code) {
        String url = wechatConfig.getCODE2ACCESS_TOKEN_URL()
                            .replace("APPID",wechatConfig.getAPPID())
                            .replace("SECRET",wechatConfig.getAPPSECRET())
                            .replace("CODE",code);
        RestTemplate restTemplate = new RestTemplate();
        //让 MappingJackson2HttpMessageConverter 能处理头部 Content-Type 为 text/plain 类型的 Json 返回值的话，
        // 我们就能让其帮我们把 Json 反序列化成我们要的对象
        restTemplate.getMessageConverters().add(new WxMappingJackson2HttpMessageConverter());
        AccessTokenByCode token = restTemplate.getForObject(url, AccessTokenByCode.class);
        log.info("AccessTokenByCode={}", token);
        return token;
    }

    public UserInfo getUserInfoByAccessToken(String accessToken, String openid) {
        String url = wechatConfig.getACCESS_TOKEN2USER_INFO_URL()
                                    .replace("ACCESS_TOKEN", accessToken)
                                    .replace("OPENID", openid);
        RestTemplate restTemplate = new RestTemplate();
        //让 MappingJackson2HttpMessageConverter 能处理头部 Content-Type 为 text/plain 类型的 Json 返回值的话，
        // 我们就能让其帮我们把 Json 反序列化成我们要的对象
        restTemplate.getMessageConverters().add(new WxMappingJackson2HttpMessageConverter());
        UserInfo userInfo = restTemplate.getForObject(url, UserInfo.class);
        log.info("UserInfo={}", userInfo);
        return userInfo;
    }
}
